
#include "FQueue.h"
#include "cc_pub.h"

/********* interior	define ***********/
#define CFG_RWLOCK_CHECK 

#define LLOG
#define LLOG_ERR
#define LLOG_MARK
#include "llog.h"

#ifdef	CFG_STATIC_BUF_ALLOCATE
#define L_MALLOC 	SMalloc
#define L_FREE(A) 	LLOG_ERR()
#else
#define L_MALLOC 	malloc
#define L_FREE(A)	free(A)
#endif
/********* interior  struct **********/
struct CC_Fixed_Queue_V4{
    uint8_t* pBuf;
	uint32_t BufSz;
	
	uint32_t ItemSz;
	uint32_t ItemNum ; // IndexMax

	uint32_t wIndex;         
    uint32_t rIndex;
	
	uint8_t  RWLock;
};

/********** global val ***************/

/******* local function **************/

/******* TODO ************************/

#ifdef CFG_MODE_FQUEUE

void FQueue_ShowObj(tFQueue* pObj){
    LLOG("tFQueue\n");
	LLOG("pBuf	  =[%x]\n",pObj->pBuf	);
	LLOG("BufSz	  =[%d]\n",pObj->BufSz	);
	LLOG("ItemSz  =[%d]\n",pObj->ItemSz	);
	LLOG("ItemNum =[%d]\n",pObj->ItemNum);
	LLOG("wIndex  =[%d]\n",pObj->wIndex	);
	LLOG("rIndex  =[%d]\n",pObj->rIndex	);
	LLOG("RWLock  =[%x]\n",pObj->RWLock	);	
}

static int FQueue_Init(tFQueue* pObj, uint32_t ItemNum, uint32_t ItemSz, uint8_t* pBuf){ 
    
	int ret = RET_ERR;
    int i;
	uint8_t* ptmp;
	
	if( (pObj == NULL) || (pBuf == NULL)\
	|| (ItemSz == 0) || (ItemNum == 0)){
		LLOG_ERR();
		return ret;
	}
	ret = RET_OK;
	
	ptmp=(uint8_t*)pObj;
	for(i=0;i<sizeof(tFQueue);i++){
		ptmp[i]=0;
	}
	pObj->pBuf 	= pBuf;
	pObj->ItemNum = ItemNum; 
	pObj->ItemSz = ItemSz; 
	pObj->BufSz = ItemNum*ItemSz; 
	
    return ret;   
}

tFQueue* FQueue_Create(uint32_t ItemNum, uint32_t ItemSz){
	
	tFQueue* ptmp = NULL;
	uint8_t* pBuf = NULL;

	if((ItemNum == 0) || (ItemSz == 0)){
		return ptmp;
	}
	
	ptmp=(tFQueue*)L_MALLOC(sizeof(tFQueue));
	if(ptmp == NULL){
		LLOG_ERR();
		return ptmp;
	}
	pBuf=L_MALLOC(ItemNum*ItemSz);
	if(pBuf == NULL){
		L_FREE(ptmp);
		LLOG_ERR();
		return NULL;
	}
	
	FQueue_Init(ptmp, ItemNum, ItemSz,pBuf);

	return ptmp;
}

uint32_t FQueue_Enque(tFQueue* pObj,uint32_t dLen, uint8_t* pPkg){

	uint8_t* pBuf;
    uint32_t rIndex;
    uint32_t wIndex;
    uint32_t Ofs;
    uint32_t LoopSz;

    uint32_t i;
    uint32_t CopySz;
    uint32_t ItemSz;	
    
	CopySz=0;
    if( (pObj== NULL) || (pPkg == NULL) || (dLen == 0) ){
        return CopySz;
    }
	
	#if CC_BFIFO_RWLOCK_OC
	if(pObj->RWLock != 0){
		return CopySz;
	}
	#endif
	pObj->RWLock = 1; // n-API 互斥
	
	wIndex = pObj->wIndex;
	rIndex = pObj->rIndex;
	LoopSz = pObj->ItemNum;
	ItemSz = pObj->ItemSz;
	
	LOOP_CALC(CopySz,wIndex,rIndex,LoopSz);		 // empty 
	CopySz -= 1;
	
	if(CopySz > 0){	
		pBuf = pObj->pBuf;
		Ofs=ItemSz*wIndex;
		
		CopySz = (dLen > ItemSz)?ItemSz:dLen;
		for (i=0; i<CopySz; i++) {
			pBuf[Ofs++] = pPkg[i];
		}
		for (; i<ItemSz; i++) {
			pBuf[Ofs++] = 0;
		}
		
		wIndex++;
		wIndex = (wIndex < LoopSz)?wIndex:0;
		pObj->wIndex = wIndex;
	}
	else{
		LLOG_MARK();
	}
	
	pObj->RWLock=0;
    return CopySz;
}

uint32_t FQueue_Deque(tFQueue* pObj,uint32_t RBufSz, uint8_t* pRBuf){

	uint8_t* pBuf;
    uint32_t rIndex;
    uint32_t wIndex;
    uint32_t Ofs;
    uint32_t LoopSz;

    uint32_t i;
    uint32_t CopySz;
	uint32_t ItemSz;
    
	CopySz=0;
    if( (pObj== NULL) || (pRBuf == NULL) || (RBufSz == 0) ){
        return CopySz;
    }
	
	#if CC_BFIFO_RWLOCK_OC
	if(pObj->RWLock != 0){
		return CopySz;
	}
	#endif
	pObj->RWLock = 1; // n-API 互斥
	
	wIndex = pObj->wIndex;
	rIndex = pObj->rIndex;
	LoopSz = pObj->ItemNum;
	ItemSz = pObj->ItemSz;
	
	LOOP_CALC_ZERO(CopySz,rIndex,wIndex,LoopSz);		 // RecvNum 
	
	if(CopySz > 0){	
		pBuf = pObj->pBuf;
		Ofs=ItemSz*rIndex;
		
		CopySz = (RBufSz < ItemSz)?RBufSz:ItemSz;
		// ItemSz = (RBufSz < ItemSz)?RBufSz:ItemSz;
		for (i=0; i<CopySz; i++) {
			pRBuf[i] = pBuf[Ofs];
			pBuf[Ofs++] = 0;
		}
		// ItemSz = pObj->ItemSz;
		for (; i<ItemSz; i++) {
			pBuf[Ofs++] = 0;
		}
		rIndex++;
		rIndex = (rIndex < LoopSz)?rIndex:0;
		pObj->rIndex = rIndex;
	}
	else{
		LLOG_MARK();
	}
	
	pObj->RWLock=0;
    return CopySz;
}

uint32_t FQueue_Peek(tFQueue* pObj,uint32_t RBufSz, uint8_t* pRBuf){

	uint8_t* pBuf;
    uint32_t rIndex;
    uint32_t wIndex;
    uint32_t Ofs;
    uint32_t LoopSz;

    uint32_t i;
    uint32_t CopySz;
	uint32_t ItemSz;
    
	CopySz=0;
    if( (pObj== NULL) || (pRBuf == NULL) || (RBufSz == 0) ){
        return CopySz;
    }
	
	#if CC_BFIFO_RWLOCK_OC
	if(pObj->RWLock != 0){
		return CopySz;
	}
	#endif
	pObj->RWLock = 1; // n-API 互斥
	
	wIndex = pObj->wIndex;
	rIndex = pObj->rIndex;
	LoopSz = pObj->ItemNum;
	ItemSz = pObj->ItemSz;
	
	LOOP_CALC_ZERO(CopySz,rIndex,wIndex,LoopSz);		 // RecvNum 
	
	if(CopySz > 0){	
		pBuf = pObj->pBuf;
		Ofs=ItemSz*rIndex;
		
		CopySz = (RBufSz < ItemSz)?RBufSz:ItemSz;
		for (i=0; i<CopySz; i++) {
			pRBuf[i] = pBuf[Ofs];
			// pBuf[Ofs++] = 0;
		}

	}
	else{
		LLOG_MARK();
	}
	
	pObj->RWLock=0;
    return CopySz;
}

uint32_t FQueue_DropOne(tFQueue* pObj){

	uint8_t* pBuf;
    uint32_t rIndex;
    uint32_t wIndex;
    uint32_t LoopSz;

    uint32_t CopySz;
	uint32_t ItemSz;
    
	CopySz=0;
    if( pObj== NULL ){
        return CopySz;
    }
	
	#if CC_BFIFO_RWLOCK_OC
	if(pObj->RWLock != 0){
		return CopySz;
	}
	#endif
	pObj->RWLock = 1; // n-API 互斥
	
	wIndex = pObj->wIndex;
	rIndex = pObj->rIndex;
	LoopSz = pObj->ItemNum;
	ItemSz = pObj->ItemSz;
	
	LOOP_CALC_ZERO(CopySz,rIndex,wIndex,LoopSz);		 // RecvNum 
	
	if(CopySz > 0){	
		
		CopySz =ItemSz ;
		rIndex++;
		rIndex = (rIndex < LoopSz)?rIndex:0;
		pObj->rIndex = rIndex;
	}
	else{
		LLOG_MARK();
	}
	
	pObj->RWLock=0;
    return CopySz;
}

#endif


